<template>
  <div class="upload-container">
    <!-- 标题 -->
    <div v-if="!hidTitle" class="upload-title">
      <span v-if="!isRead && !noRequire" class="required-marker">*</span>
      {{ title || '附件' }}
    </div>

    <!-- 图片预览 + 上传区域统一放在 grid 容器里 -->
    <transition-group name="fade-scale" tag="div" class="grid-container">
      <!-- 文件预览区域 -->
      <div v-for="(img, index) in previewList" :key="index" class="preview-item">
        <div v-if="!isImageFile(img.ext)" class="icon-wrapper">
          <img :src="getIconByType(img.ext)" alt="文档图标" class="doc-icon" />
        </div>
        <img v-else :src="img.url" class="preview-img" alt="img.name" />

        <button class="delete-btn" @click="removeImage(index)">×</button>
      </div>

      <!-- 图片上传区域 -->
      <div v-if="!isRead && (!maxCount || previewList.length < maxCount)" class="upload-area" @click="triggerFileInput" :key="'upload'">
        <input id="fileInput" type="file" accept="image/*,.pdf,.doc,.docx,.xls,.xlsx" multiple @change="handleFileChange" hidden />
      </div>
    </transition-group>
  </div>
</template>

<script setup>
import wordIcon from '@/assets/images/word.png';
import pdfIcon from '@/assets/images/pdf.png';
import excelIcon from '@/assets/images/excel.png';
import { ref } from 'vue';
// ========== Props & Emits ==========
const props = defineProps([
  'value',
  'isRead',
  'noRequire',
  'hidTitle',
  'title',
  'maxCount', // 最大上传数量（可选）
  'compressQuality', // 压缩质量 (0.1 - 1.0)
  'maxParallel' // 最大并行压缩数量，默认 3
]);

const emit = defineEmits(['update:value']);

// ========== State ==========
const previewList = ref([...(props.value || [])]);
const workerPool = ref([]);
const files = ref([]);
const newImages = ref([]);

// ========== 工具函数 ==========
// 获取文件后缀
const getFileExt = (filename) => {
  const parts = filename.split('.');
  return parts[parts.length - 1].toLowerCase();
};

// 判断是否是图片
const isImageFile = (ext) => {
  return ['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(ext);
};

// 获取图标
const getIconByType = (ext) => {
  switch (ext) {
    case 'doc':
    case 'docx':
      return wordIcon;
    case 'xls':
    case 'xlsx':
      return excelIcon;
    case 'pdf':
      return pdfIcon;
    default:
      return null;
  }
};

// ========== Worker 相关逻辑 ==========
// 初始化 Worker 池
const initWorkerPool = () => {
  const poolSize = props.maxParallel || 3;
  workerPool.value = [];
  for (let i = 0; i < poolSize; i++) {
    const worker = new Worker(new URL('@/utils/compressWorker.js', import.meta.url), {
      type: 'module'
    });

    workerPool.value.push({
      worker,
      busy: false
    });

    // 接收压缩结果
    worker.onmessage = (e) => {
      const { index, url, file } = e.data;

      newImages.value[index] = {
        url,
        file,
        name: file.name,
        ext: getFileExt(file.name)
      };

      // 回收该 Worker
      const workerItem = workerPool.value.find((item) => item?.worker === worker);
      if (workerItem) {
        workerItem.busy = false;
      }

      // 检查是否全部完成
      if (newImages.value.every((img) => img)) {
        previewList.value = [...previewList.value, ...newImages.value];
        emit('update:value', previewList.value);
      }
    };

    worker.onerror = (error) => {
      console.error('Worker 发生错误:', error);
    };
  }
};
// 找一个空闲的 Worker
const getAvailableWorker = () => {
  return workerPool.value.find((w) => !w.busy);
};

// 分配单个任务给可用 Worker
const assignTaskToWorker = (file, index) => {
  const availableWorker = getAvailableWorker();
  if (!availableWorker) {
    setTimeout(() => assignTaskToWorker(file, index), 500);
    return;
  }

  availableWorker.busy = true;
  const reader = new FileReader();
  reader.onload = () => {
    availableWorker.worker.postMessage({
      file,
      url: reader.result,
      quality: props.compressQuality || 0.7,
      index
    });
  };
  reader.onerror = (error) => {
    console.error('文件读取错误:', error);
  };
  reader.readAsDataURL(file);
};

// 文件改变处理
const handleFileChange = (event) => {
  files.value = Array.from(event.target.files);

  if (props.maxCount && previewList.value.length + files.value.length > props.maxCount) {
    alert(`最多只能上传 ${props.maxCount} 个文件`);
    return;
  }

  newImages.value = new Array(files.value.length).fill(null);

  // 分配任务给空闲 Worker
  files.value.forEach((file, index) => {
    const ext = getFileExt(file.name);

    // 如果是图片且需要压缩，交给 Worker 处理
    if (isImageFile(ext) && props.compressQuality) {
      assignTaskToWorker(file, index);
    } else {
      // 非图片或不需要压缩，直接添加
      const reader = new FileReader();
      reader.onload = () => {
        newImages.value[index] = {
          url: reader.result,
          file,
          name: file.name,
          ext
        };

        if (newImages.value.every((img) => img !== null)) {
          previewList.value = [...previewList.value, ...newImages.value];
          emit('update:value', previewList.value);
        }
      };
      reader.onerror = (error) => {
        console.error('文件读取错误:', error);
      };
      reader.readAsDataURL(file);
    }
  });
};

// 删除图片
const removeImage = (index) => {
  previewList.value.splice(index, 1);
  emit('update:value', previewList.value);
};

// 触发文件选择
const triggerFileInput = () => {
  document.getElementById('fileInput').click();
};

// 在组件挂载时初始化 Worker 池
onMounted(() => {
  initWorkerPool();
});
</script>

<style scoped lang="less">
// 定义变量
@primary-color: #2196f3;
@danger-color: #f44336;
@hover-color: #1976d2;
@border-color: #ccc;
@bg-color: #f9f9f9;
@icon-bg-color: #fafafa;
@text-gray: #666;

// 定义混合
.border-radius(@radius: 8px) {
  border-radius: @radius;
}

.transition(@property: all, @duration: 0.3s,@ease: ease) {
  transition: @property @duration @ease;
}

.common-btn() {
  position: absolute;
  bottom: 20px;
  padding: 10px 20px;
  border: none;
  .border-radius();
  color: white;
  font-size: 16px;
  cursor: pointer;
  .transition();
}

// 容器布局
.upload-container {
  padding: 4px;
  font-family: Arial, sans-serif;
}

.upload-title {
  font-size: 16px;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
}

// 上传区域
.upload-area {
  border: 2px dashed @border-color;
  .border-radius();
  width: 100%;
  aspect-ratio: 1 / 1;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: @bg-color;
  cursor: pointer;
  position: relative;
  overflow: hidden;

  &::before {
    content: '+';
    font-size: 40px;
    color: #888;
  }
}

// 网格容器
.grid-container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  padding: 6px 16px;
}

.preview-item {
  width: 100%;
  height: 100%;
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  .border-radius();
  background-color: #eee;
}

.preview-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  cursor: pointer;
}

.icon-wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: @icon-bg-color;
  .border-radius();
  border: 1px dashed @border-color;
}

.doc-icon {
  width: 60px;
  height: auto;
  margin-bottom: 4px;
}

.file-ext-label {
  font-size: 12px;
  color: @text-gray;
}

// 删除按钮
.delete-btn {
  position: absolute;
  top: 4px;
  right: 4px;
  background-color: rgba(0, 0, 0, 0.5);
  color: white;
  border: none;
  .border-radius(50%);
  width: 24px;
  height: 24px;
  font-size: 16px;
  line-height: 22px;
  text-align: center;
  cursor: pointer;
}

// 动画相关
.fade-scale-enter-active,
.fade-scale-leave-active {
  .transition();
}

.fade-scale-enter-from,
.fade-scale-leave-to {
  opacity: 0;
  transform: scale(0.8);
}

.zoom-enter-active {
  animation: zoom-in 0.3s ease;
}

.zoom-leave-active {
  animation: zoom-out 0.3s ease;
}

@keyframes zoom-in {
  from {
    transform: scale(0.8);
    opacity: 0;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}

@keyframes zoom-out {
  from {
    transform: scale(1);
    opacity: 1;
  }
  to {
    transform: scale(0.8);
    opacity: 0;
  }
}

.slide-up-enter-active {
  animation: slide-up 0.3s ease;
}

.slide-up-leave-active {
  animation: slide-up 0.3s reverse;
}

@keyframes slide-up {
  from {
    transform: translateY(20px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

// 功能按钮
.download-btn {
  .common-btn();
  left: 20px;
  background-color: @primary-color;

  &:hover {
    transform: scale(1.1);
    background-color: @hover-color !important;
  }
}

.close-btn {
  .common-btn();
  right: 20px;
  background-color: @danger-color;

  &:hover {
    transform: scale(1.1);
    background-color: @hover-color !important;
  }
}

// 新增样式，提取内联样式
.required-marker {
  color: red;
  margin-right: 4px;
  margin-top: 8px;
}
</style>
